package cc.laop.support.realm;

import cc.laop.business.system.UserBusiness;
import cc.laop.constants.UserConstants;
import cc.laop.entity.system.Resource;
import cc.laop.entity.system.Role;
import cc.laop.entity.system.User;
import com.google.code.kaptcha.Constants;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;


public class AccountAuthorizingRealm extends AuthorizingRealm {

	@Autowired
	private UserBusiness userBusiness;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		User user = (User) getSession()
				.getAttribute(UserConstants.CURRENT_USER);
		if (user == null) {
			throw new AuthenticationException("User is not exist!");
		}
		SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
		if (user != null) {
			if (user.getRoleList() != null) {
				for (Role role : user.getRoleList()) {
					simpleAuthorInfo.addRole(role.getName());
					if (role.getResourceList() != null) {
						for (Resource resource : role.getResourceList()) {
							simpleAuthorInfo.addStringPermission(
									resource.getPermission());
						}
					}
				}
			}
		}
		return simpleAuthorInfo;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		CustomUsernamePasswordToken token = (CustomUsernamePasswordToken) authcToken;
		Session session = getSession();
		String code = (String) session
				.getAttribute(Constants.KAPTCHA_SESSION_KEY);
		if (token.getCaptcha() == null) {
			throw new AuthenticationException(
					"验证码不能为空 !");
		}
		if (!token.getCaptcha().equalsIgnoreCase(code)) {
			throw new AuthenticationException("验证码错误!");
		}
		if (StringUtils.isEmpty(token.getUsername())
				|| ArrayUtils.isEmpty(token.getPassword())) {
			throw new AuthenticationException(
					"用户名和密码不能为空 !");
		}
		User user = userBusiness.getUserByEmail(token.getUsername());
		if (user != null) {
			if (user.getStatus() == UserConstants.STATUS_DISABLE) {
				throw new AuthenticationException("用户禁止登陆!");
			}
			AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(
					user.getEmail(), user.getPassword(), this.getName());
			setSession(UserConstants.CURRENT_USER, user);
			return authcInfo;
		} else {
			throw new AuthenticationException("用户不存在!");
		}

	}

	@Override
	protected void assertCredentialsMatch(AuthenticationToken token,
			AuthenticationInfo info) throws AuthenticationException {
		CredentialsMatcher cm = getCredentialsMatcher();
		if (!cm.doCredentialsMatch(token, info)) {
			// 密码验证不通过
			String msg = "Password is wrong!";
			throw new IncorrectCredentialsException(msg);
		}
	}

	/**
	 * 保存登录名
	 */
	private void setSession(Object key, Object value) {
		Session session = getSession();
		if (null != session) {
			session.setAttribute(key, value);
		}
	}

	private Session getSession() {
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession(false);
		if (session == null) {
			session = subject.getSession();
		}
		if (session != null) {
			return session;
		}
		return null;
	}

}
